package com.longge.websocket.endpoint;

import java.io.IOException;
import java.util.Optional;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.longge.websocket.configuration.MySocketConfiguration;
import com.longge.websocket.dto.ClientTextMessage;
import com.longge.websocket.interceptor.WebSocketInterceptor;
import com.longge.websocket.util.MessageSenderUtils;
import com.longge.websocket.util.MyMessageSenderUtils;
import com.longge.websocket.util.MySessionUtils;
import com.longge.websocket.util.SessionUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 除了@ServerEndpoint外，
 * 还可以通过WebSocketConfigurer注册WebSocketHandler，并通过HttpSessionHandshakeInterceptor来对请求进行拦截(鉴权、清洗敏感字等)处理。
 * @see MyWebSocketHandler
 * @see MySocketConfiguration
 * @see MyMessageSenderUtils
 * @see MySessionUtils
 * @see WebSocketInterceptor
 * 
 * @author roger yang
 *
 */
@Slf4j
@Component
@ServerEndpoint("/ws/1/{uid}")
public class WebSocketServer {
	private static final String SYSTEM = "system";
	
	@OnOpen
	public void onOpen(@PathParam("uid")String userId, Session session) {
		log.info("User:{} enter", userId);
		SessionUtils.addSession(userId, session);
		MessageSenderUtils.sendTextMsgToAll(SYSTEM, "user：" + userId + " enter");
	}
	
	@OnClose
	public void onClose(Session session) {
		String userId = SessionUtils.removeSession(session);
		log.info("User:{} leave", userId);
		MessageSenderUtils.sendTextMsgToAll(SYSTEM, "user：" + userId + " leave");
	}
	
	@OnMessage
	public void onMessage(String message, Session session) {
		Optional<String> op = SessionUtils.getUserIdBySession(session);
		if(op.isPresent()) {
			String userId = op.get();
			log.info("User:{} send message:{}", userId, message);
			try {
				ClientTextMessage dto = JSONObject.parseObject(message, ClientTextMessage.class);
				if(StringUtils.isBlank(dto.getMessage())) {
					return;
				}
				if(StringUtils.isNotBlank(dto.getToUserId())) {
					boolean success = MessageSenderUtils.sendTextMsgToUser(userId, dto.getToUserId(), dto.getMessage());
					if(!success) {
						MessageSenderUtils.sendTextMsgToUser(SYSTEM, userId, "user " + dto.getToUserId() + " is offline");
					}
				} else {
					MessageSenderUtils.sendTextMsgToAll(userId, message);
				}
			} catch (Exception e) {
				log.error("Parsing foreground parameter error, close this session");
				try {
					MessageSenderUtils.sendTextMsgToUser(SYSTEM, userId, "Illegal request, socket close");
					SessionUtils.removeSession(session);
					session.close();
				} catch (IOException e1) {
					log.error("session close error", e1);
				}
			}
		}
	}
	
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("websocket error", error);
    }

}
